package fun.codedesign.principle.princple6.a003.dependence_inversion;

import org.junit.Test;

import fun.codedesign.principle.advice151.Notice;

import java.util.ArrayList;
import java.util.List;

interface Handler<Request, Response> {

    void execute(Request request, Response response, Chain<Request, Response> chain);

}

interface Chain<Request, Response> {

    void doInvoke(Request request, Response response);

    void register(Handler<Request, Response> handler);

    void unRegister(Handler<Request, Response> handler);

    void destory();

}

/**
 * 依赖导致原则 <br>
 * <pre>
 * </pre>
 *
 * @author zengjian
 * @create 2018-07-11 14:18
 * @since 1.0.0
 */
@Notice("即基于接口编程，而不基于具体实现，所以被称为控制反转")
public class DependenceInversionPrincple {

    public static void main(String[] args) throws InterruptedException {
        final Chain<String, String> chain = new DefaultChain<>();
        chain.register(new DefaultHandler<String, String>());
        chain.register(new CustomHandler<String, String>());
        for (int i = 0; i < 3; i++) {
            new Thread() {
                @Override
                public void run() {
                    chain.doInvoke("123", "123");
                }
            }.start();
        }
        System.out.println(Thread.currentThread().isDaemon());
        Thread.currentThread().join();
    }


    @Test
    public void test() throws InterruptedException {
        final Chain<String, String> chain = new DefaultChain<>();
        chain.register(new DefaultHandler<String, String>());
        chain.register(new CustomHandler<String, String>());
        for (int i = 0; i < 3; i++) {
            new Thread() {
                @Override
                public void run() {
                    chain.doInvoke("123", "123");
                }
            }.start();
        }
        System.out.println(Thread.currentThread().isDaemon());
        Thread.currentThread().join(3000);
    }
}

class DefaultChain<Request, Response> implements Chain<Request, Response> {

    private List<Handler<Request, Response>> chainList;
    private ThreadLocal<Integer> order = new ThreadLocal<Integer>();

    public DefaultChain() {
        chainList = new ArrayList<>();
    }

    /**
     * 安全性问题
     *
     * @param request
     * @param response
     */
    @Override
    public void doInvoke(Request request, Response response) {
        // 如果为空先进行初始化
        if (order.get() == null) {
            order.set(0);
        }
        int index = order.get();
        System.out.println(Thread.currentThread().getName() + ":" + order.get());
        order.set(order.get() + 1);
        if (index < chainList.size()) {
            chainList.get(index).execute(request, response, this);
        } else {
            // 重新复位
            order.set(0);
            return;
        }
    }

    @Override
    public void register(Handler<Request, Response> handler) {
        chainList.add(handler);
    }

    @Override
    public void unRegister(Handler<Request, Response> handler) {
        chainList.remove(handler);
    }

    @Override
    public void destory() {
        chainList.clear();
    }
}

class DefaultHandler<Request, Response> implements Handler<Request, Response> {

    @Override
    public void execute(Request request, Response response, Chain<Request, Response> chain) {
        // doSomething
        System.out.println("执行线程：" + Thread.currentThread().getName() + "  执行Handler:" + this.getClass().getSimpleName());
        chain.doInvoke(request, response); // 传递到下一个handler
    }
}

class CustomHandler<Request, Response> implements Handler<Request, Response> {
    @Override
    public void execute(Request request, Response response, Chain<Request, Response> chain) {
        System.out.println("执行线程：" + Thread.currentThread().getName() + "  执行Handler:" + this.getClass().getSimpleName());
        chain.doInvoke(request, response); // 传递到下一个handler
    }
}


/**
 * 基于接口进行编程
 */



